package co.edu.unal.bioingenium.kbmed.retrieval.text.process;

import co.edu.unal.bioingenium.kbmed.config.Configuration;
import co.edu.unal.bioingenium.kbmed.features.CompactFeatureVector;
import co.edu.unal.bioingenium.kbmed.text.filter.FilterPipe;
import co.edu.unal.bioingenium.kbmed.text.representation.vo.Corpus;
import co.edu.unal.bioingenium.kbmed.retrieval.vo.QueryDocument;
import co.edu.unal.bioingenium.kbmed.retrieval.weighting.TFIDF;
import gnu.trove.map.TObjectIntMap;
import gnu.trove.map.hash.TObjectIntHashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import uk.ac.shef.wit.simmetrics.similaritymetrics.AbstractStringMetric;
import uk.ac.shef.wit.simmetrics.similaritymetrics.Levenshtein;

/**
 *
 * @author Alejandro Riveros Cruz
 */
public class QueryByWords {

    /**
     * 
     */
    public static int QUERY_FEATURE_TYPE = Configuration.FEATURE_ALL_TO_1;
    /**
     * 
     */
    private FilterPipe filterPipe = new FilterPipe();
    /**
     * 
     */
    private AbstractStringMetric stringMetric;

    /**
     * 
     */
    public QueryByWords() {
        stringMetric = new Levenshtein();
        if (Configuration.QUERY_FEATURE_TYPE.equals("frequency")) {
            QUERY_FEATURE_TYPE = Configuration.FEATURE_FREQUENCY;
        } else if (Configuration.QUERY_FEATURE_TYPE.equals("relativefrequency")) {
            QUERY_FEATURE_TYPE = Configuration.FEATURE_RELATIVE_FREQUENCY;
        } else if (Configuration.QUERY_FEATURE_TYPE.equals("TFIDF")) {
            QUERY_FEATURE_TYPE = Configuration.FEATURE_TF_IDF;
        } else if (Configuration.QUERY_FEATURE_TYPE.equals("allto1")) {
            QUERY_FEATURE_TYPE = Configuration.FEATURE_ALL_TO_1;
        }
    }

    /**
     *
     * @param queryString
     * @param corpus
     * @return  
     */
    public QueryDocument mapQueryToWords(String queryString, Corpus corpus) {
        QueryDocument queryDocument = new QueryDocument(queryString);
        TObjectIntMap<String> queryWords = new TObjectIntHashMap<String>();
        List<String> words = filterPipe.filter(queryString);
        for (String word : words) {
            if (corpus.containsWord(word)) {
                if (queryWords.containsKey(word)) {
                    queryWords.increment(word);
                } else {
                    queryWords.put(word, 1);
                }
            }
        }
        queryDocument.setWordList(queryWords);
        extractQueryFeatures(queryDocument, corpus);
        return queryDocument;
    }

    /**
     *
     * @param queryDocument
     * @param corpus 
     */
    private void extractQueryFeatures(QueryDocument queryDocument, Corpus corpus) {
        TObjectIntMap<String> invertedSortedWordList = corpus.getInvertedSortedWordList();
        float value;
        CompactFeatureVector featureVector = new CompactFeatureVector();
        switch (QueryByWords.QUERY_FEATURE_TYPE) {
            case Configuration.FEATURE_FREQUENCY:
                for (String word : queryDocument.getWordList().keySet()) {
                    value = (float) queryDocument.getWordList().get(word);
                    featureVector.setValue(invertedSortedWordList.get(word), value);
                }
                break;
            case Configuration.FEATURE_RELATIVE_FREQUENCY:
                for (String word : queryDocument.getWordList().keySet()) {
                    value = (float) queryDocument.getWordList().get(word) / (float) queryDocument.getWordList().size();
                    featureVector.setValue(invertedSortedWordList.get(word), value);
                }
                break;
            case Configuration.FEATURE_TF_IDF:
                for (String word : queryDocument.getWordList().keySet()) {
                    value = (float) TFIDF.getTFIDF(queryDocument.getWordOccurrences(word), queryDocument.getTotalWords(), corpus.getTotalDocuments() + 1, corpus.getDocumentOcurrences(word) + 1);
                    featureVector.setValue(invertedSortedWordList.get(word), value);
                }
                featureVector.normalize();
                break;
            case Configuration.FEATURE_ALL_TO_1:
                for (String word : queryDocument.getWordList().keySet()) {
                    featureVector.setValue(invertedSortedWordList.get(word), 1f);
                }
                featureVector.normalize();
                break;
        }
        queryDocument.setFeatureVector(featureVector);
    }

    /**
     *
     * @param queryDocument 
     * @return  
     */
    public QueryDocument expandWords(QueryDocument queryDocument) {
        throw new UnsupportedOperationException();
    }

    /**
     * 
     * @param queryDocument
     * @return
     */
    public Set<String> getSurgeryWords(QueryDocument queryDocument) {
        //TODO: what is better a radixtree or use a spell library with the wordList as dictionary??
        Set<String> tempSet = new HashSet<String>();
        for (String conceptId : queryDocument.getWordList().keySet()) {
        }

        return tempSet;
    }
}
